package uk.ac.glasgow.oose2.gcf.model.operation.acc;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import uk.ac.glasgow.oose2.gcf.model.Accumulator;
import uk.ac.glasgow.oose2.gcf.model.CalculatorException;

public abstract class AccRefOperation extends AccOperation<Double> {

	private int numArgs;
	
	public AccRefOperation(Stack<Double> stack, List<Accumulator> accumulators, int numArgs) {
		super(stack, accumulators);
		this.numArgs = numArgs;
	}

	@Override
	public void invoke() throws CalculatorException {
		Double b;
		try{
			b = stack.pop();
		} catch (Exception e){
			throw new CalculatorException(
					"Accumulator op", "empty stack");
		}
		int index = (int) (b + 0.1);
		Accumulator acc = null;
		try {
			acc =  accumulators.get(index);
		} catch (IndexOutOfBoundsException ioe){
			throw new CalculatorException(
					"Accumulator op", "invalid accumulator index.");
		}
		
		List<Double> args = new ArrayList<Double>();
		
		try {
			int i = 0;
			while (i < numArgs){
				args.add(stack.pop());
				i++;
			}
		} catch (Exception ex) {
			throw new CalculatorException("accumulator op", "empty stack");
		}
		
		stack.push(doOp(acc,args));
	}
	
	protected abstract Double doOp(Accumulator acc, List<Double> args) throws CalculatorException;

}
